﻿using UnityEngine;
using UnityEngine.UI;

namespace FutureCorePlugin
{
    public class PreUIHandler : MonoBehaviour
    {
        public enum UILayer : int
        {
            Background = 20,
            Bottom = 40,
            Normal = 60,
            Top = 80,
            Popup = 100,
            Highest = 120,
            Loading = 140,
            Tips = 160,
            System = 180,
        }

        public static PreUIHandler Instance { get; private set; }

        private GameObject preUIRoot;
        private GameObject uiCanvasGo;
        private Canvas uiCanvas;
        private Camera uiCamera;
        private CanvasScaler uiCanvasScaler;

        private GameObject loadingLayer;
        private GameObject tipsLayer;
        private GameObject systemLayer;

        private void Awake()
        {
            Instance = this;

            Init();
            InitLayer();
            InitAdaptiveCamera();
            InitAdaptive();
        }

        private void OnDestroy()
        {
            Instance = null;
        }

        private void Init()
        {
            preUIRoot = Instantiate(Resources.Load<GameObject>("Preset/PreUI/PreUIRoot"));
            uiCanvasGo = preUIRoot.transform.Find("[UI]/UIRoot/UICanvas").gameObject;
            uiCanvas = uiCanvasGo.GetComponent<Canvas>();
            uiCamera = uiCanvas.worldCamera;
            uiCanvasScaler = uiCanvasGo.GetComponent<CanvasScaler>();

            loadingLayer = uiCanvasGo.transform.Find("Loading").gameObject;
            tipsLayer = uiCanvasGo.transform.Find("Tips").gameObject;
            systemLayer = uiCanvasGo.transform.Find("System").gameObject;

            preUIRoot.name = "PreUIRoot";
            preUIRoot.transform.SetParent(transform, false);

            DebugUtil.Log("[PreUIHandler]Init PreUI");
        }

        private void InitLayer()
        {
            uiCanvas.overridePixelPerfect = false;
            uiCanvas.pixelPerfect = false;
            uiCanvas.overrideSorting = true;
            uiCanvas.sortingLayerName = SortingLayerConst.UI;
            uiCanvas.sortingOrder = 0;

            AddLayerCanvas(loadingLayer, UILayer.Loading);
            AddLayerCanvas(tipsLayer, UILayer.Tips);
            AddLayerCanvas(systemLayer, UILayer.System);
        }

        private void AddLayerCanvas(GameObject layerGo, UILayer uiLayer)
        {
            Canvas canvas = layerGo.AddComponent<Canvas>();
            canvas.overridePixelPerfect = false;
            canvas.pixelPerfect = false;
            canvas.overrideSorting = true;
            canvas.sortingLayerName = SortingLayerConst.UI;
            canvas.sortingOrder = (int)uiLayer;

            GraphicRaycaster graphicRaycaster = layerGo.AddComponent<GraphicRaycaster>();
            graphicRaycaster.ignoreReversedGraphics = true;
            graphicRaycaster.blockingObjects = GraphicRaycaster.BlockingObjects.None;
        }

        private void InitAdaptiveCamera()
        {
            CameraAdaptive adaptiveCom = uiCamera.gameObject.AddComponent<CameraAdaptive>();
            adaptiveCom.isOrthographic = true;
            adaptiveCom.orthographicSize = AdaptiveConst.OrthographicSize_1920H;
        }

        private void InitAdaptive()
        {
            uiCanvasScaler.gameObject.AddComponent<UGUIAdaptive>();

            loadingLayer.AddComponent<CanvasRootAdaptive>();
            tipsLayer.AddComponent<CanvasRootAdaptive>();
            systemLayer.AddComponent<FillCanvasRootAdaptive>();
        }

        public T CreateInstanceUI<T>() where T : BasePreUI<T>
        {
            GameObject go = new GameObject(typeof(T).Name);
            go.layer = PLayerMaskConst.UI;
            RectTransform goRtf = go.AddComponent<RectTransform>();
            goRtf.anchorMin = Vector2.zero;
            goRtf.anchorMax = Vector2.one;
            goRtf.sizeDelta = Vector2.zero;

            T ui = go.AddComponent<T>();
            ui.Init();
            InitInstanceUI(ui);
            ui.Bind();
            return ui;
        }

        public void InitInstanceUI<T>(BasePreUI<T> ui) where T : BasePreUI<T>
        {
            ui.uiGO = Instantiate(Resources.Load<GameObject>(ui.resPath));
            ui.uiTF = ui.uiGO.transform;
            ui.uiTF.transform.SetParent(ui.gameObject.transform, false);

            SetUILayer(ui.gameObject, ui);
        }

        private void SetUILayer<T>(GameObject uiGo, BasePreUI<T> ui) where T : BasePreUI<T>
        {
            GameObject layerGo = null;
            UILayer uiLayer = ui.uiLayer;
            switch (uiLayer)
            {
                case UILayer.Loading:
                    layerGo = loadingLayer;
                    break;
                case UILayer.Tips:
                    layerGo = tipsLayer;
                    break;
                case UILayer.System:
                    layerGo = systemLayer;
                    break;
            }
            uiGo.transform.SetParent(layerGo.transform, false);
            int index = uiGo.transform.GetSiblingIndex();
            int sortingOrder = (int)uiLayer + index;
            ui.uiSortingOrder = sortingOrder;

            Canvas canvas = uiGo.AddComponent<Canvas>();
            canvas.overridePixelPerfect = false;
            canvas.pixelPerfect = false;
            canvas.overrideSorting = true;
            canvas.sortingLayerName = SortingLayerConst.UI;
            canvas.sortingOrder = ui.uiSortingOrder;

            GraphicRaycaster graphicRaycaster = uiGo.AddComponent<GraphicRaycaster>();
            graphicRaycaster.ignoreReversedGraphics = true;
            graphicRaycaster.blockingObjects = GraphicRaycaster.BlockingObjects.None;
        }

        public void Close()
        {
            if (gameObject)
            {
                Destroy(gameObject);
            }

            DebugUtil.Log("[PreUIHandler]Close PreUI");
        }
    }
}